#include <iostream>
#include <iomanip>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>



using namespace std;

void *print_message_function1( void *ptr );


extern "C" { int wait(int *);}
const int N = 254;

int main()
{

int pid_t, pid, ret;

struct timeval tv1, tv2;
struct timezone tz1, tz2;
unsigned long total;

struct timeval tv1_t, tv2_t;
struct timezone tz1_t, tz2_t;
unsigned long total_t;

pthread_t thread1, thread2;
char *message1 = "Thread 1";
char *message2 = "Thread 2";
int  iret1, iret2;


// fixed format for floating point I/O
cout.setf(ios::fixed, ios::floatfield);
cout.setf(ios::showpoint);
cout.precision(5);
// start time


//Creating N processes and caluclating the total creation time
gettimeofday(&tv1, &tz1);

for (int i=0; i <= N; i++) 
{

pid_t = fork();
if (pid_t == 0) exit(ret);
//pid = wait(&ret);
}

// end time

gettimeofday(&tv2, &tz2);
 

// total time used in microseconds

total = (tv2.tv_sec - tv1.tv_sec)*1000000 +(tv2.tv_usec - tv1.tv_usec);

     // Creating threads and caluclating avergae thread creation time

     pthread_attr_t attr;
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

     gettimeofday(&tv1_t, &tz1_t);
     for (int i=0; i <= N; i++)
     {

     iret1 = pthread_create( &thread1, &attr, print_message_function1, (void*) message1);
     //iret2 = pthread_create( &thread2, &attr, print_message_function2, (void*) message2);
     }
     pthread_attr_destroy(&attr);

     gettimeofday(&tv2_t, &tz2_t);
     // total time used in microseconds
     total_t = (tv2_t.tv_sec - tv1_t.tv_sec)*1000000 +(tv2_t.tv_usec - tv1_t.tv_usec);


cout << "The average time taken for N processes vs N Threads"<<endl;
cout << "Processes(254)     "<< "Threads(254) "<<endl;
cout << "----------------------------------- "<<endl;

cout <<total_t/(double(1000)*double(N))<<" ms          "<<total/(double(1000)*double(N))<< " ms"<<endl;

//cout << "The average time taken for N threads: "<< total_t/(double(1000)*double(N)) << " milliseconds. " << endl;
//cout << "The avergae time taken for each N processes: "<< total/(double(1000)*double(N)) << " milliseconds. " << endl;

return 0;

}

void *print_message_function1( void *ptr )
{    
     // No thread statements are being run just to caluclate the thread creation time
     //char *message;
     //message = (char *) ptr;
     //sched_yield();
     //for(int i=0;i<100;i++)
    //   cout << i << endl << flush;
     pthread_exit((void *) 0);
}

void *print_message_function2( void *ptr )
{
     // No thread statements are being run just to caluclate the thread creation time
     //char *message;
     //message = (char *) ptr;
     //for(int i=0;i<100;i++)
    //   cout << i << endl << flush;
     pthread_exit((void *) 0);
}

